import json

from django.http import Http404
from django.http import HttpResponse
from django.http import JsonResponse
from django.shortcuts import render
from django.views import View
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.generics import GenericAPIView
from rest_framework import status

from booktest.models import BookInfo
from booktest.serializers import BookInfoSerializer
# Create your views here.
# ================+自定义Mixin扩展类================
class BookListModelMixin(object):
    def list(self,request,*args,**kwargs):
        """获取一组数据的通用代码"""
        # 1. 查询所有的图书的数据
        qs = self.get_queryset() # QuerySet
        # 2. 返回所有图书的json的数据，状态码: 200
        serializer = self.get_serializer(qs, many=True)
        return Response(serializer.data)

class MyCreateModelMixin(object):
    def create(self,request,*args,**kwargs):
        """创建一条数据的通用流程代码"""
        # 1. 获取参数btitle和bpub_date并进行校验
        # 反序列化-数据校验
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        # 反序列化-数据保存(新增) -> create
        serializer.save()
        # 3. 返回新增的图书的json数据，状态码: 201
        return Response(serializer.data, status=status.HTTP_201_CREATED)

# /books/
class BookListView(BookListModelMixin,
                   MyCreateModelMixin,
                   GenericAPIView):
    # 指定当前视图所使用的序列化器类
    serializer_class = BookInfoSerializer
    # 指定当前视图所使用的查询集
    queryset = BookInfo.objects.all()
    def get(self, request):
        """
        self.kwargs: 字典，保存从url地址中提取的所有命名参数
        获取所有的图书的信息：
        1. 查询所有的图书的数据
        2. 返回所有图书的json的数据
        """
        return self.list(request)

    def post(self, request):
        """
        新增一本图书的信息：
        1. 获取参数btitle和bpub_date并进行校验
        2. 创建图书信息并添加进数据表中
        3. 返回新增的图书的json数据，状态码: 201
        """
        # 需求: 前端需要传递新增图书的信息(btitle, bpub_date)，通过json传递
        return self.create(request)

class MyRetrieveModelMixin(object):
    def retrieve(self, request, *args, **kwargs):
        """获取指定对象数据的通用流程"""
        # 1.从视图所使用的查询集中获取指定的对象
        book = self.get_object()
        # 2.将指定的对象序列化并返回，状态码: 200
        serializer = self.get_serializer(book)
        return Response(serializer.data)

class UpdateModelMixin(object):
    def update(self,request,*args,**kwargs):
        """更新指定对象数据的通用流程"""
        # 1. 从视图所使用的查询集中查询指定的对象
        obj = self.get_object()
        # 2. 获取参数(btitle, bpub_date)并进行校验
        # 反序列化-数据校验
        serializer = self.get_serializer(obj, data=request.data)
        serializer.is_valid(raise_exception=True)
        # 反序列化-数据保存(更新) -> update
        serializer.save()
        # 4. 返回修改图书的json数据，状态码：200
        return Response(serializer.data)

class MyDestroyModelMixin(object):
    def destroy(self,requesst,*args,**kwargs):
        """删除指定对象数据的通用流程"""
        # 1. 从视图所使用的查询集中获取指定的对象
        book = self.get_object()
        # 2. 删除对应的数据
        book.delete()
        # 3. 返回响应，状态码: 204
        return Response(status=status.HTTP_204_NO_CONTENT)

# /books/(?P<pk>\d+)/
# /books/9/
class BookDetailView(MyRetrieveModelMixin,
                     UpdateModelMixin,
                     MyDestroyModelMixin,
                     GenericAPIView):
    # 指定当前视图所使用的序列化器类
    serializer_class = BookInfoSerializer
    # 指定当前视图所使用的查询集
    queryset = BookInfo.objects.all()

    # HttpRequest类的对象
    def get(self, request, pk):
        """
        self.kwargs['pk']
        获取指定的图书的信息：
        1. 根据pk获取指定的图书对象
        2. 将图书的json数据返回，状态码: 200
        """
        return self.retrieve(request)

    def put(self, request, pk):
        """
        修改指定的图书的信息：
        1. 根据pk获取指定的图书对象
        2. 获取参数(btitle, bpub_date)并进行校验
        3. 修改指定的图书的数据并更新数据表
        4. 返回修改图书的json数据，状态码：200
        """
        # 需求：需要前端传递修改的图书的数据(btitle, bpub_date)，通过json传递
        return self.update(request)

    def delete(self, request, pk):
        """
        删除指定的图书的信息：
        1. 根据pk获取指定的图书对象
        2. 删除对应的数据
        3. 返回响应，状态码: 204
        """
        return self.destroy(request)

